/* **************************************************
 * User Group Manager
 *      author:     Baskin Tapkan - baskint@hotmail.com
 *          written for Code Plex
 *              April - 2008
 *                  http://tapkan.com
 * ****************************************************
 */

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace UserGroupManager
{
    public partial class UserGrpMembership : Form
    {
        #region "Properties"
        string computerName = string.Empty;
        string domainName = "<your_domain_name>";
        DataSet userInfo;
        int selectedIndex = 0;
        // list of groups to remove from the membership
        List<string> groupsToRemove = new List<string>();

        public string ComputerName
        {
            get { return computerName; }
            set { computerName = value; }
        }
        #endregion

        public UserGrpMembership(string systemName)
        {
            computerName = systemName;
            InitializeComponent();
            this.Text = "Groups by user at " + computerName;
        }

        /// <summary>
        /// Onload fired event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void UserGrpMembership_Load(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            UserMgr um = new UserMgr();
            um.ComputerName = computerName;
            userInfo = um.GetAllLocalUsers();

            GroupMgr gm = new GroupMgr();
            gm.ComputerName = computerName;
            gm.DomainName = domainName;

            // make sure dataset comes back with records
            if (userInfo.Tables[0].Rows.Count > 0)
            {

                for (int i = 0; i < userInfo.Tables[0].Rows.Count; i++)
                    cmbUserName.Items.Add(userInfo.Tables[0].Rows[i]["UserName"].ToString());
                cmbUserName.SelectedIndex = selectedIndex;
                UpdateUI(0);            // update the UI with the first user
            }
            this.Cursor = Cursors.Default;
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        /// <summary>
        /// User account changed event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmbUserName_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            lsbMemberGroups.Items.Clear();
            lsbAvailableGroups.Items.Clear();
            lblNumMemberGroups.Text = "";
            lblNumAvailable.Text = "";
            if (userInfo.Tables[0].Rows.Count > 0)
            {
                selectedIndex = cmbUserName.SelectedIndex;
                UpdateUI(selectedIndex);
            }
            this.Cursor = Cursors.Default;
        }

        /// <summary>
        /// Puts the user into the group
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnMakeMember_Click(object sender, EventArgs e)
        {
            int numSelected = lsbAvailableGroups.SelectedItems.Count;
            string userName = cmbUserName.Text;

            groupsToRemove.Clear();     // clear out this List<string> type

            if (numSelected == 1)
            {
                // move one group
                string groupName = lsbAvailableGroups.SelectedItems[0].ToString();
                AddUIMember(userName, groupName);
            }
            else if (numSelected > 1)
            {
                // move multiple groups
                foreach (string groupName in lsbAvailableGroups.SelectedItems)
                {
                    AddUIMember(userName, groupName);
                }

            }
            RemoveGroupsUI(false);
        }

        /// <summary>
        /// Puts the current user into all available groups
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnMakeMemberAll_Click(object sender, EventArgs e)
        {
            string userName = cmbUserName.Text;
            groupsToRemove.Clear();

            foreach (string groupName in lsbAvailableGroups.Items)
            {
                AddUIMember(userName, groupName);
            }
            RemoveGroupsUI(false);
        }

        /// <summary>
        /// Removes current user from the selected group
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnRemoveMember_Click(object sender, EventArgs e)
        {
            int numSelected = lsbMemberGroups.SelectedItems.Count;
            string userName = cmbUserName.Text;
            groupsToRemove.Clear();

            if (numSelected == 1)
            {
                // transfer one group
                string groupName = lsbMemberGroups.SelectedItems[0].ToString();
                RemoveUIMember(userName, groupName);
            }
            else if (numSelected > 1)
            {
                // iterate over selectedGroups
                foreach (string groupName in lsbMemberGroups.SelectedItems)
                {
                    RemoveUIMember(userName, groupName);
                }
            }
            RemoveGroupsUI(true);
        }

        /// <summary>
        /// Removes current user from all member groups
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnRemoveMemberAll_Click(object sender, EventArgs e)
        {
            string userName = cmbUserName.Text;
            groupsToRemove.Clear();

            foreach (string groupName in lsbMemberGroups.Items)
            {
                RemoveUIMember(userName, groupName);
            }
            RemoveGroupsUI(true);
        }

        /// <summary>
        /// Persists the changes
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnApply_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            string userName = cmbUserName.Text;

            // instantiate the UserMgr object
            UserMgr um = new UserMgr();
            um.ComputerName = computerName;
            bool result = false;

            GroupMgr gm = new GroupMgr();
            gm.ComputerName = computerName;

            // add them to groups
            foreach (string memberGroup in lsbMemberGroups.Items)
            {
                if (!gm.IsMember(userName, memberGroup))
                {
                    // if the user is not a member, add it to the group
                    result = um.AddToGroup(memberGroup, userName);
                }
            }

            // clean up for membership
            foreach (string availableGroup in lsbAvailableGroups.Items)
            {
                if (gm.IsMember(userName, availableGroup))
                {
                    // if the group is available (designated as not member), remove from group
                    result = um.RemoveFromGroup(availableGroup, userName);
                }
            }

            staMembership.Items[0].Text = "Membership changes are applied";
            this.Cursor = Cursors.Default;


        }

        #region "Helper methods"

        private void UpdateUI(int rowIndex)
        {
            cmbUserName.Text = userInfo.Tables[0].Rows[rowIndex]["UserName"].ToString();
            txtFullName.Text = userInfo.Tables[0].Rows[rowIndex]["FullName"].ToString();
            txtDescription.Text = userInfo.Tables[0].Rows[rowIndex]["Description"].ToString();

            // updates the available groups list box
            UpdateAvailableGroups();
            // updates the member groups list box - this will also take the groups 
            // which are members from the available groups, thus should execute after the one above
            UpdateMemberGroups(cmbUserName.Text);
            lblNumAvailable.Text = "Available Groups: " + lsbAvailableGroups.Items.Count.ToString();
            lblNumMemberGroups.Text = "Member Groups: " + lsbMemberGroups.Items.Count.ToString();
        }

        private List<string> GetAllLocalGroups()
        {
            List<string> localGroups;
            // set the groupmanager object
            GroupMgr gm = new GroupMgr();
            gm.ComputerName = computerName;

            // get the list of groups
            localGroups = gm.GetLocalGroups();

            return localGroups;
        }

        private List<string> GetAllMemberGroups(string userName)
        {
            List<string> localGroups;
            List<string> memberGroups = new List<string>();
            GroupMgr gm = new GroupMgr();
            gm.ComputerName = computerName;

            localGroups = gm.GetLocalGroups();

            foreach (string groupName in localGroups)
            {
                bool isMember = gm.IsMember(userName, groupName);
                if (isMember)
                {
                    memberGroups.Add(groupName);
                }
            }
            return memberGroups;
        }

        private void UpdateAvailableGroups()
        {
            lsbAvailableGroups.Items.Clear();
            List<string> localGroups = GetAllLocalGroups();
            if (localGroups.Count > 0)
            {
                foreach (string s in localGroups)
                {
                    // add each group to the pertinent list
                    lsbAvailableGroups.Items.Add(s);
                }
            }
        }

        private void UpdateMemberGroups(string userName)
        {
            lsbMemberGroups.Items.Clear();

            List<string> memberGroups = GetAllMemberGroups(userName);
            if (memberGroups.Count > 0)
            {
                foreach (string memberGroup in memberGroups)
                {
                    lsbMemberGroups.Items.Add(memberGroup);
                    lsbAvailableGroups.Items.Remove(memberGroup);
                }
            }
        }

        private void AddUIMember(string userName, string groupName)
        {
            if (!lsbMemberGroups.Items.Contains(groupName))
            {
                lsbMemberGroups.Items.Add(groupName);
                // need to store this in a separate list since iterator does not
                // allow iterating over changing lists
                groupsToRemove.Add(groupName);
                lsbAvailableGroups.Refresh();
                lsbMemberGroups.Refresh();
            }
        }

        private void RemoveUIMember(string userName, string groupName)
        {
            if (!lsbAvailableGroups.Items.Contains(groupName))
            {
                lsbAvailableGroups.Items.Add(groupName);
                // need to store this in a separate list since iterator does not
                // allow iterating over changing lists
                groupsToRemove.Add(groupName);
                lsbAvailableGroups.Refresh();
                lsbMemberGroups.Refresh();
            }
        }

        private void RemoveGroupsUI(bool groupMember)
        {
            if (groupMember)
            {
                foreach (string s in groupsToRemove)
                {
                    lsbMemberGroups.Items.Remove(s);
                }
            }
            else
            {
                foreach (string s in groupsToRemove)
                {
                    lsbAvailableGroups.Items.Remove(s);
                }
            }
            lblNumAvailable.Text = "Available Groups: " + lsbAvailableGroups.Items.Count.ToString();
            lblNumMemberGroups.Text = "Member Groups: " + lsbMemberGroups.Items.Count.ToString();
        }

        #endregion

        
    }
}